#include "CameraManager.h"
//#include "DX11InputManager.h"
#include "Timer.h"
#include "D3DXVECTOROperators.h"
#include "DX11HelpfulFunctions.h"
#include "StringUtilities.h"
#include "Game.h"

#include <math.h>
#include <WinUser.h>

CameraManager::CameraManager()
{
	m_pos = D3DXVECTOR3(0.0f, 0.0f, -10.0f);
	m_target = D3DXVECTOR3(0.01f, 0.0f, 0.01f);
	m_up = D3DXVECTOR3(0.0f, 1.0f, 0.0f);
	m_miniMapPos = D3DXVECTOR3(0.0f, 20.0f, -10.0f);	
	m_vel = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
	m_angleV = 1.6319839f;
	m_angleH = 0.010237293f;
	m_mouseLeftDown = false;
	m_rotAngle = 0;
	m_zoom =  0.0f;
	m_zoomVel = 0.0f;

	m_xRot = 0;
	m_yRot = 0;
	m_zRot = 0;

	m_moveAcc = 0.0f;
	m_moveVel = 0.0f;

	m_wKeyDown = false;
	m_aKeyDown = false;
	m_sKeyDown = false;
	m_dKeyDown = false;
	m_pgUpKeyDown = false;
	m_pgDownKeyDown = false;

	m_lMouseButtonDown = false;
	m_rMouseButtonDown = false;
	m_mouseWheelDelta = 0.0f;

	TheEventPoller::Instance()->AddHandler(this);

	m_camera.position = Vec3f(0.0f, 1.5f, -10.0f);
	
	Vec3f camLookAt(0.0f, 0.0f, 0.0f);
	m_camera.direction = camLookAt - m_camera.position;
	m_camera.direction.Normalise();

	m_camera.right.CrossProduct(Vec3f(0.0f, 1.0f, 0.0f), m_camera.direction);
	m_camera.right.Normalise();
	m_camera.down.CrossProduct(m_camera.right, m_camera.direction);	

	m_spaceBarDown = false;
	m_ctrlDown = false;
}

CameraManager::~CameraManager()
{
	TheEventPoller::Instance()->RemoveHandler(this);
}

void CameraManager::Draw()
{
}

void CameraManager::Update()
{
	UpdateMain();	
}

void CameraManager::UpdateMain()
{
	float dt = TheTimer::Instance()->GetDt();
	static float time = 0.0f;
	static float addAmount = 0.1f;
	time += dt;
	if (time > 0.001f)
	{
		if (m_aKeyDown)
		{
			m_camera.position.x += addAmount;
		}
		else if(m_dKeyDown)
		{
			m_camera.position.x -= addAmount;
		}

		if (m_wKeyDown)
		{
			m_camera.position.z += addAmount;
		}
		else if (m_sKeyDown)
		{
			m_camera.position.z -= addAmount;
		}

		if (m_spaceBarDown)
		{
			m_camera.position.y += addAmount;
		}
		else if (m_ctrlDown)
		{
			m_camera.position.y -= addAmount;
		}

		time = 0.0f;
	}
	Vec3f up(0.0f, 1.0f, 0.0);
	Vec3f camLookAt(sin(m_angleH) * 10.0f, cos(m_angleV) * 10.0f, 0.0f);
	m_camera.direction = camLookAt - m_camera.position;
	m_camera.direction.Normalise();

	m_camera.right.CrossProduct(up, m_camera.direction);
	m_camera.right.Normalise();
	m_camera.down.CrossProduct(m_camera.right, m_camera.direction);	


	////m_keyboardState = TheDX11InputManager::Instance()->GetKeyPressed();
	////m_mouseState = TheDX11InputManager::Instance()->GetMouseState();

	//m_moveAcc = 0.25f * TheTimer::Instance()->GetDt();
	//float mouseMoveSpeed = TheTimer::Instance()->GetDt();
	//float dt = TheTimer::Instance()->GetDt();


	//// mouse checks
	//// mouse motions


	//float moveAmountX = 0;
	//float moveAmountZ = 0;

	//	// mouse zoom
	//m_zoomVel -= m_mouseWheelDelta * dt * 1.0001f;


	//m_mouseWheelDelta *= (5.0f * dt);
	//LimitCameraMovements();

	//// keyboard checks
	//if (m_pgUpKeyDown)
	//{
	//	m_zoomVel -= 2.5f * dt;
	//}
	//else if (m_pgDownKeyDown)
	//{
	//	m_zoomVel += 2.5f * dt;
	//}
	//
	//if (m_aKeyDown)
	//{
	//	moveAmountX += sin(m_angleV + (float)M_PI) * sin(m_angleH + (float)M_PI_2) * m_moveAcc * 2.5f;
	//	moveAmountZ += sin(m_angleV + (float)M_PI) * cos(m_angleH + (float)M_PI_2) * m_moveAcc * 2.5f;

	//	//moveAmountX -= sin(m_angleH) * sin(m_angleV) * m_moveAcc * 2.0f;
	//	//moveAmountZ -= sin(m_angleH) * cos(m_angleV) * m_moveAcc * 2.0f;
	//	//m_vel -= D3DXVECTOR3(moveAmountX, 0, moveAmountZ);

	//}
	//if (m_dKeyDown)
	//{
	//	moveAmountX -= sin(m_angleV + (float)M_PI) * sin(m_angleH + (float)M_PI_2) * m_moveAcc * 2.5f;
	//	moveAmountZ -= sin(m_angleV + (float)M_PI) * cos(m_angleH + (float)M_PI_2) * m_moveAcc * 2.5f;
	//	//m_vel += D3DXVECTOR3(moveAmountX, 0, moveAmountZ);
	//	//moveAmountX += sin(m_angleH) * sin(m_angleV) * m_moveAcc * 2.0f;
	//	//moveAmountZ += sin(m_angleH) * cos(m_angleV) * m_moveAcc * 2.0f;
	//}
	//if (m_sKeyDown)
	//{
	//	moveAmountX -= sin(m_angleV) * sin(m_angleH) * m_moveAcc * 2.0f;
	//	moveAmountZ -= sin(m_angleV) * cos(m_angleH) * m_moveAcc * 2.0f;
	//	//m_vel += D3DXVECTOR3(moveAmountX, 0, moveAmountZ);
	//}
	//if (m_wKeyDown)
	//{
	//	moveAmountX += sin(m_angleV) * sin(m_angleH) * m_moveAcc * 2.0f;
	//	moveAmountZ += sin(m_angleV) * cos(m_angleH) * m_moveAcc * 2.0f;
	//	//m_vel -= D3DXVECTOR3(moveAmountX, 0, moveAmountZ);
	//}


	//m_vel -= D3DXVECTOR3(moveAmountX, 0, moveAmountZ);
	//// set target to picked position
	//m_zoom += m_zoomVel;
	//if (m_zoom < 2.0f)
	//{
	//	m_zoom = 2.0f;
	//}
	//m_pos += m_vel;
	//m_target = D3DXVECTOR3(
	//	sin(m_angleV) * sin(m_angleH) * m_zoom, 
	//	cos(m_angleV) * m_zoom, 
	//	sin(m_angleV) * cos(m_angleH) * m_zoom 
	//	);

	////D3DXVec3Mult(&m_vel, D3DXVECTOR3(0.9f, 0.9f, 0.9f));
	//	
	//D3DXMatrixLookAtLH(&m_view, &D3DXVECTOR3(m_target + m_pos), &m_pos, &m_up);

	//TheScreenManager::Instance()->SetViewMatrix(m_view);
	//
	//m_zoomVel *= 0.9f;
	//m_vel *= 0.9f;

}

CSCamera& CameraManager::GetCamera()
{
	return m_camera;
}

void CameraManager::SetBirdsEyeViewMatrix()
{
	D3DXMATRIX result;
	m_miniMapPos.x = m_pos.x;
	m_miniMapPos.z = m_pos.z;
	D3DXVECTOR3 target(-0.00005627f, 60.000000f, -1.21489796f);
	//D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);

	D3DXMatrixLookAtLH(&result, &D3DXVECTOR3(m_pos + D3DXVECTOR3(m_target.x, 60.0f, m_target.z)), &m_pos, &m_up);
	TheScreenManager::Instance()->SetBEV(result);
}

void CameraManager::LimitCameraMovements()
{
	if (m_zoom > 500.0f)
	{
		m_zoom = 500.0f;
	}
}

const D3DXVECTOR3& CameraManager::GetCameraPos() const
{
	return m_pos;
}

const D3DXVECTOR3& CameraManager::GetLookAt() const
{
	return m_target;
}

void CameraManager::AddEventHandler()
{
	TheEventPoller::Instance()->AddHandler(this);
}

void CameraManager::RemoveEventHandler()
{
	TheEventPoller::Instance()->RemoveHandler(this);
}

void CameraManager::OnKeyDownEvent(const WPARAM& event)
{		
	if (event == VK_UP)
	{
		m_pgUpKeyDown = true;
	}
	else if (event == VK_DOWN)
	{
		m_pgDownKeyDown = true;
	}

	//if (event == VK_SPACE)
	//{
	//	m_spaceBarDown = true;
	//}
	//if (event == VK_LSHIFT)
	//{
	//	m_ctrlDown = true;
	//}

	char c = MapVirtualKey(event, MAPVK_VK_TO_CHAR);

	//m_moveAcc = 0.1f * TheTimer::Instance()->GetDt();
	if(c == 'A')
	{
		m_moveVel += m_moveAcc;
		m_aKeyDown = true;
	}
	if(c == 'D')
	{
		m_moveVel += m_moveAcc;
		m_dKeyDown = true;
	}
	if(c == 'W')
	{
		m_moveVel += m_moveAcc;
		m_wKeyDown = true;
	}
	if(c == 'S')
	{
		m_moveVel += m_moveAcc;
		m_sKeyDown = true;
	}
	if(c == 'R')
	{
		m_angleH = -2.4f;
	}
	if(c == 'Z')
	{
		m_zKeyDown = true;
		m_spaceBarDown = true;
	}
	if(c == 'X')
	{
		m_xKeyDown = true;
		m_ctrlDown = true;
	}
}

void CameraManager::OnKeyUpEvent(const WPARAM& event)
{	
	if (event == VK_UP)
	{
		m_pgUpKeyDown = false;
	}
	else if (event == VK_DOWN)
	{
		m_pgDownKeyDown = false;
	}

	if (event == VK_SPACE)
	{
		m_spaceBarDown = false;
	}
	else if (event == VK_LCONTROL)
	{
		m_ctrlDown = false;
	}



	char c = MapVirtualKey(event, MAPVK_VK_TO_CHAR);

	if(c == 'A')
	{
		m_aKeyDown = false;
	}
	if(c == 'D')
	{
		m_dKeyDown = false;
	}
	if(c == 'W')
	{
		m_wKeyDown = false;
	}
	if(c == 'S')
	{
		m_sKeyDown = false;
	}
	if(c == 'Z')
	{
		m_zKeyDown = false;
		m_spaceBarDown = false;
	}
	if(c == 'X')
	{
		m_xKeyDown = false;
		m_ctrlDown = false;
	}
}

void CameraManager::OnMouseMotionEvent(const LPARAM& event)
{
	float differenceH = 0.0f;
	float differenceV = 0.0f;

	int x = LOWORD(event);
	int y = HIWORD(event);

	bool mouseInBoundsX = false;
	bool mouseInBoundsY = false;

	int screenWidth = TheScreenManager::Instance()->GetWindowWidth();
	int screenHeight = TheScreenManager::Instance()->GetWindowHeight();

	if (x <= screenWidth && x >= 0)
	{
		//m_mouseX = x;
		mouseInBoundsX = true;
	}
	if (y <= screenHeight && y >= 0)
	{
		//m_mouseY = y;
		mouseInBoundsY = true;
	}

	if (m_lMouseButtonDown && mouseInBoundsX && mouseInBoundsY)
	{
		differenceH = m_currentMouseX - (float)x;
		differenceV = m_currentMouseY - (float)y;

		m_currentMouseX = (float)x;
		m_currentMouseY = (float)y;

		differenceH /= 8.0f;
		differenceV /= 8.0f;

		differenceH *= (float)(D3DX_PI / 180.0f);
		differenceV *= (float)(D3DX_PI / 180.0f);

		m_angleH += differenceH;
		m_angleV -= differenceV;
	}
}

void CameraManager::OnMouseButtonDownEvent(const MSG& event)
{
	// left mouse button down

	if (event.message == WM_LBUTTONDOWN)
	{
		m_currentMouseX = LOWORD(event.lParam);
		m_currentMouseY = HIWORD(event.lParam);
		m_lMouseButtonDown = true;
	}
	else if (event.message == WM_RBUTTONDOWN)
	{
		m_rMouseButtonDown = true;
		//D3DXVECTOR3 mousePos = DX11::Get3DMousePos(D3DXVECTOR2(m_currentMouseX, m_currentMouseY));
		float t = 0;
	}
}

void CameraManager::OnMouseButtonUpEvent(const MSG& event)
{
	// left mouse button up
	if (event.message == WM_LBUTTONUP)
	{
		m_lMouseButtonDown = false;
	}
	else if (event.message == WM_RBUTTONUP)
	{
		m_rMouseButtonDown = false;
	}
}

void CameraManager::OnMouseWheelEvent(const WPARAM& event)
{
	m_mouseWheelDelta = GET_WHEEL_DELTA_WPARAM(event);
	if (m_mouseWheelDelta < 0)
	{
		//m_pgDownKeyDown = true;
		m_mouseWheelDelta = -10.0f;
	}
	else
	{
		m_mouseWheelDelta = 10.0f;
		//m_pgUpKeyDown = true;
	}
}